#pragma once
#include <iostream>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <cstring>
#include <cerrno>

#include <pthread.h>

#include "logMessage.hpp"
#include "err.hpp"
#include "Sock.hpp"

// sudo firewall-cmd --zone=public --add-port=8888/tcp --permanent
// firewall-cmd --reload
// firewall-cmd --zone=public --list-ports

namespace ns_HttpServer
{
    class HttpServer;
    using func_t = std::function<std::string(std::string &)>;

    class ThreadData
    {
    public:
        ThreadData(int sock, HttpServer *pts) : _sock(sock), _pTS(pts)
        {
        }

        int _sock;
        HttpServer *_pTS;
    };

    class HttpServer
    {
    public:
        HttpServer(func_t func, uint16_t port) : _func(func), _port(port)
        {
        }
        ~HttpServer()
        {
            _listensock.Close();
        }

        void InitServer()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();

            logMessage(Debug, "Init TcpServer success listenSock : %d", _listensock.Fd());
        }

        void StartServer()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;

                int sock = _listensock.Accept(&clientip, &clientport);
                if (sock < 0)
                    continue;


                logMessage(Info,"SOCK:%d",sock);
                logMessage(Info, "accept a user info : ip %s | port:%d", clientip.c_str(), clientport);

                pthread_t tid;
                ThreadData *td = new ThreadData(sock, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *pTD = static_cast<ThreadData *>(args);
            pTD->_pTS->HandlerHttpRequest(pTD->_sock);

            //服务器主动断开连接
            close(pTD->_sock);
            delete pTD;
            return nullptr;
        }

        //处理http请求
        void HandlerHttpRequest(int sock)
        {
            // TODO...
            char buffer[40960];

            ssize_t s = recv(sock, buffer, sizeof(buffer), 0);
            if (s > 0)
            {
                buffer[s] = 0;
                std::string message = buffer;
                std::string res = _func(message);
                logMessage(Info,"Send str:%s",res.c_str());
                send(sock, res.c_str(), res.size(), 0);
            }
            else
            {
                logMessage(Debug,"recv no message");
            }

            //close(sock);
        }

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };

}